﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JewererBasic.Models;
using Zen.Barcode.Web.Mvc;
using Zen.Barcode;
using Zen.Barcode.Web;
using System.IO;

namespace JewererBasic.Controllers
{
    public class OrderController : Controller
    {
        private MSQDBEntities db = new MSQDBEntities();

        #region Search
        public ActionResult Index()
        {
            var queryList = (from d in db.ORDERs
                             select d).ToList();
            //IEnumerable<ORDER> query = null;

            //if (String.IsNullOrEmpty(searchIdOrderValue) == false)
            //{
            //    query = queryList.Where(m => m.IdOrder.Contains(searchIdOrderValue));
            //}

            //if (String.IsNullOrEmpty(searchIdCustomerValue) == false)
            //{
            //    query = queryList.Where(m => m.IdCustomer.Contains(searchIdCustomerValue));
            //}

            //int x;
            //if (Int32.TryParse(searchStartWeekValue, out x) == true)
            //{
            //    query = queryList.Where(m => m.StartWeek == x).ToList();
            //}

            //if (Int32.TryParse(searchFinishWeekValue, out x) == true)
            //{
            //    query = queryList.Where(m => m.FinishWeek == x);
            //}

            //if (query == null)
            //{
            //    return View(queryList);
            //}

            return View(queryList.OrderByDescending(m => m.DayMake));
        }

        private static string searchIdOrderValue = null;
        private static string searchIdCustomerValue = null;
        private static string searchStartWeekValue = null;
        private static string searchFinishWeekValue = null;
        [HttpPost]
        public ActionResult Index(FormCollection fc)
        {
            if (fc["submit"] == "SEARCH")
            {
                searchIdOrderValue = fc["tbIdOrderSearch"];
                searchIdCustomerValue = fc["tbIdCustomerSearch"];
                searchStartWeekValue = fc["tbStartWeekSearch"];
                searchFinishWeekValue = fc["tbFinishWeekSearch"];
            }
            else if (fc["submit"] == "CREATE")
            {
                return RedirectToAction("CreateNewOrder");
            }

            var queryList = (from d in db.ORDERs
                             select d).ToList();
            IEnumerable<ORDER> query = null;

            if (String.IsNullOrEmpty(searchIdOrderValue) == false)
            {
                query = queryList.Where(m => m.IdOrder.Contains(searchIdOrderValue));
            }

            if (String.IsNullOrEmpty(searchIdCustomerValue) == false)
            {
                query = queryList.Where(m => m.IdCustomer.Contains(searchIdCustomerValue));
            }

            int x;
            if (Int32.TryParse(searchStartWeekValue, out x) == true)
            {
                query = queryList.Where(m => m.StartWeek == x).ToList();
            }

            if (Int32.TryParse(searchFinishWeekValue, out x) == true)
            {
                query = queryList.Where(m => m.FinishWeek == x);
            }

            if (query == null)
            {
                return View(queryList);
            }

            return View(query.OrderByDescending(m => m.DayMake).ToList());
        }
        #endregion

        #region Hien thi chi tiet 1 Order
        public ActionResult Details(string id = null)
        {
            searchStrOrder = null;
            searchStrOrderProduct = null;
            searchIdOrderValue = null;
            searchIdCustomerValue = null;
            searchStartWeekValue = null;
            searchFinishWeekValue = null;

            // Lay thong tin chung cua order
            ORDER o = db.ORDERs.Find(id);
            if (o == null)
            {
                return RedirectToAction("Index");
            }

            // Lay ve list cac products trong order
            var query = from d in db.ORDER_PRODUCT
                        where d.IdOrder == id
                        select d;

            List<OrderProduct> productsInOrder = new List<OrderProduct>();
            List<ProcessOfBag> processes = new List<ProcessOfBag>();
            ProcessOfBag tmpProcess = null;
            foreach (var item in query.ToList())
            {
                OrderProduct op = new OrderProduct();
                op.Index = productsInOrder.Count + 1;
                op.ProductId = item.IdProduct;
                op.KindId = item.Kind;
                op.Kind = kinds.Where(m => m.Id == op.KindId).Select(m => m.Name).FirstOrDefault();
                op.Size = item.Size;
                op.Weight = Math.Round(item.Weight, 3);
                op.Quantity = item.Number;

                foreach (var bag in item.BAGs)
                {
                    foreach (var pro in bag.BAG_PROCESS)
                    {
                        if (pro.PROCESS.Type == 1)
                        {
                            foreach (var p in processes)
                            {
                                tmpProcess = null;

                                if (p.Name == pro.PROCESS.Name)
                                {
                                    tmpProcess = p;
                                    break;
                                }
                            }

                            if (tmpProcess != null)
                            {
                                if (pro.DateOut.HasValue)
                                {
                                    tmpProcess.Finish++;
                                }
                                else
                                {
                                    tmpProcess.Waiting++;
                                }
                            }
                            else
                            {
                                tmpProcess = new ProcessOfBag();
                                tmpProcess.Name = pro.PROCESS.Name;
                                if (pro.DateOut.HasValue)
                                {
                                    tmpProcess.Finish++;
                                }
                                else
                                {
                                    tmpProcess.Waiting++;
                                }

                                processes.Add(tmpProcess);
                            }
                        }
                    }
                }

                productsInOrder.Add(op);
            }

            return View(new OrderDetail() { Order = o, Products = productsInOrder, Processes = processes });
        }
        #endregion

        #region Tao Order + BagNos

        private static ItemOrder order = new ItemOrder
        {
            Order = new ORDER(),
            Products = new List<OrderProduct>()
        };
        private List<KIND> kinds = new List<KIND>((new MSQDBEntities()).KINDs.ToList());
        public ActionResult CreateNewOrder()
        {
            kinds = new List<KIND>((new MSQDBEntities()).KINDs.ToList());

            ViewBag.Kinds = kinds;

            return View(new OrderViewModel());
        }

        [HttpPost]
        public ActionResult CreateNewOrder(FormCollection fc)
        {
            return RedirectToAction("Index");
        }

        private void DivideBagNos(ORDER o, List<ProductOrderViewModel> productions)
        {
            //ORDER order = db.ORDERs.Find(id);

            string id = o.IdOrder;

            // Truy van chi tiet cac product co trong don dat hang
            var productInOrder = from d in db.ORDER_PRODUCT
                                 where d.IdOrder == (id)
                                 select d;

            int tmpIndex = 0;
            string tmpId;
            BAG b = db.BAGs.ToList().LastOrDefault();
            if (b == null)
            {
                tmpIndex = 0;
            }
            else
            {
                Int32.TryParse(b.Id, out tmpIndex);
            }

            // chia bag
            int nItem = 0;
            int nInBag = 0;
            int count = 0; // dem so bag trong 1 order
            int index = 0;
            foreach (var item in productInOrder)
            {
                // Lay ve cac Process ung voi IdProduct
                var processOfProductQuery = from d in db.PRODUCT_PROCESS
                                            where d.IdProduct.Equals(item.IdProduct)
                                            orderby d.ProcessOrder ascending
                                            select d;
                List<PRODUCT_PROCESS> processOfProduct = processOfProductQuery.ToList();

                nItem = item.Number;
                nInBag = productions[index++].ProductsInBag;
                while (nItem > 0)
                {
                    // Tinh toan so luong item trong bag va so item con lai
                    if (nItem > nInBag)
                        nItem -= nInBag;
                    else
                    {
                        nInBag = nItem;
                        nItem = 0; // het san pham -> dieu kien dung
                    }

                    // tao bag moi
                    BAG bag = new BAG();
                    tmpIndex++;
                    tmpId = tmpIndex.ToString();
                    while (tmpId.Length < 6)
                    {
                        tmpId = tmpId.Insert(0, "0");
                    }
                    bag.Id = tmpId;
                    bag.IdOrderProduct = item.Id;
                    bag.Number = nInBag;
                    bag.Finish = -1;
                    // bo sung them cac thuoc tinh neu can: manager 

                    // Tao image code
                    Code128BarcodeDraw barcode128 = BarcodeDrawFactory.Code128WithChecksum;
                    System.Drawing.Image img = barcode128.Draw(bag.Id, 40);
                    var path = Path.Combine(Server.MapPath("~/Content/Barcode"), id + "_" + bag.Id + ".png");
                    img.Save(path);

                    db.BAGs.Add(bag);
                    count++;
                    
                    // tao cac bag_process
                    for (int i = 0; i < processOfProduct.Count; i++)
                    {
                        BAG_PROCESS bagProcess = new BAG_PROCESS();
                        bagProcess.IdBag = bag.Id;
                        bagProcess.IdProcess = processOfProduct[i].IdProcess;
                        bagProcess.Time = (int)processOfProduct[i].Time;
                        bagProcess.Finish = -1;
                        // waiting process
                        BAG_PROCESS bagProcess1 = new BAG_PROCESS();
                        //string waitProName = "Waiting " + processOfProduct[i].PROCESS.Name;
                        bagProcess1.IdBag = bag.Id;
                        bagProcess1.IdProcess = bagProcess.IdProcess - 1;
                        //bagProcess1.IdProcess = db.PROCESSes.Where(m => m.Name == waitProName).Select(m => m.Id).First();
                        bagProcess1.Finish = -1;

                        db.BAG_PROCESS.Add(bagProcess);
                        db.BAG_PROCESS.Add(bagProcess1);
                    }
                    
                    // tao bag stone
                    PRODUCT p = db.PRODUCTs.Find(item.IdProduct);
                    if (p != null)
                    {
                        foreach (var s in p.PRODUCT_STONE)
                        {
                            BAG_STONE bs = new BAG_STONE();
                            bs.IdBag = bag.Id;
                            bs.IdStone = s.IdStone;
                            bs.TotalWeight = Math.Round(s.Weight * bag.Number, 3);
                            bs.TotalQty = s.Qty * bag.Number;
                            bs.Numb = 0;
                            bs.Weight = 0;

                            db.BAG_STONE.Add(bs);
                        }

                        // tao bag component
                        foreach (var c in p.PRODUCT_COMPONENT)
                        {
                            BAG_COMPONENT bc = new BAG_COMPONENT();
                            bc.IdBag = bag.Id;
                            bc.IdComponent = c.IdComponent;
                            bc.TotalWeight = Math.Round(c.Weight * bag.Number, 3);
                            bc.Weight = 0;

                            db.BAG_COMPONENT.Add(bc);
                        }

                        // tao bag mould
                        foreach (var m in p.PRODUCT_MOULD)
                        {
                            BAG_MOULD bm = new BAG_MOULD();
                            bm.IdBag = bag.Id;
                            bm.IdMould = m.IdMould;
                            bm.TotalQty = m.Qty * bag.Number;
                            bm.Numb = m.Qty;

                            db.BAG_MOULD.Add(bm);
                        }
                    }
                }
            }

            o.TotalBags = count;

            db.SaveChanges();
        }
        #endregion

        #region Hien thi Order chi tiet cac BagNo
        private static string searchStrOrder = null;
        private static string searchStrOrderProduct = null;
        public ActionResult OrderDetail(string id = null)
        {
            ORDER o = db.ORDERs.Find(id);
            if (o == null)
            {
                return RedirectToAction("Index");
            }

            // Lay cac ID cua OrderProduct
            var orderProductQuery = from d in db.ORDER_PRODUCT
                                    where d.IdOrder.Equals(id)
                                    select d;

            ViewBag.OrderProducts = orderProductQuery.Select(m => m.IdProduct).Distinct().ToList();

            IEnumerable<BAG> bagQuery;

            if (String.IsNullOrEmpty(searchStrOrder))
            {
                // Lay cac Bag cua 1 Order dua vao Id OrderProduct
                bagQuery = from d in db.BAGs
                           join c in orderProductQuery
                           on d.IdOrderProduct equals c.Id
                           select d;
            }
            else
            {
                // Lay cac Bag cua 1 Order dua vao Id OrderProduct
                bagQuery = from d in db.BAGs
                           join c in orderProductQuery
                           on d.IdOrderProduct equals c.Id
                           where d.Id.Contains(searchStrOrder)
                           select d;
            }

            if (String.IsNullOrEmpty(searchStrOrderProduct) == false)
            {
                bagQuery = bagQuery.Where(p => p.ORDER_PRODUCT.IdProduct == searchStrOrderProduct);
            }

            /*
            #region
            List<ItemBag> list = new List<ItemBag>();
            foreach (var item in bagQuery.ToList())
            {
                // lay bag
                var bag = from d in db.BAGs
                          where d.Id == item.Id
                          select d;

                // Lay cac Process tu Bag ID
                var procesOfBag = from d in db.BAG_PROCESS
                                  where d.IdBag.Equals(item.Id)
                                  select d;

                ItemBag ib = new ItemBag();
                ib.Bag = bag.First();
                ib.Processes = procesOfBag.ToList();
                list.Add(ib);
            }

            ViewBag.BagNos = list;
            ViewBag.OrderId = o.IdOrder;
            #endregion
             * */

            ViewBag.OrderId = id;

            return View(bagQuery.ToList());
        }

        [HttpPost]
        public ActionResult OrderDetail(FormCollection fc, string id = null)
        {
            if (fc["submit"] == "SEARCH")
            {
                searchStrOrder = fc["tbSearch"];
                searchStrOrderProduct = fc["ddlProductInOrder"];
            }

            ORDER o = db.ORDERs.Find(id);
            if (o == null)
            {
                return RedirectToAction("Index");
            }

            // Lay cac ID cua OrderProduct
            var orderProductQuery = from d in db.ORDER_PRODUCT
                                    where d.IdOrder.Equals(id)
                                    select d;

            ViewBag.OrderProducts = orderProductQuery.Select(m => m.IdProduct).Distinct().ToList();
            
            IEnumerable<BAG> bagQuery;

            if (String.IsNullOrEmpty(searchStrOrder))
            {
                // Lay cac Bag cua 1 Order dua vao Id OrderProduct
                bagQuery =  from d in db.BAGs
                            join c in orderProductQuery
                            on d.IdOrderProduct equals c.Id
                            select d;
            }
            else
            {
                // Lay cac Bag cua 1 Order dua vao Id OrderProduct
                bagQuery =  from d in db.BAGs
                            join c in orderProductQuery
                            on d.IdOrderProduct equals c.Id
                            where d.Id.Contains(searchStrOrder)
                            select d;
            }

            if (String.IsNullOrEmpty(searchStrOrderProduct) == false)
            {
                bagQuery = bagQuery.Where(p => p.ORDER_PRODUCT.IdProduct == searchStrOrderProduct);
            }

            /*
            #region
            List<ItemBag> list = new List<ItemBag>();
            foreach (var item in bagQuery.ToList())
            {
                // lay bag
                var bag = from d in db.BAGs
                          where d.Id == item.Id
                          select d;

                // Lay cac Process tu Bag ID
                var procesOfBag = from d in db.BAG_PROCESS
                                  where d.IdBag.Equals(item.Id)
                                  select d;

                ItemBag ib = new ItemBag();
                ib.Bag = bag.First();
                ib.Processes = procesOfBag.ToList();
                list.Add(ib);
            }

            ViewBag.BagNos = list;
            ViewBag.OrderId = o.IdOrder;
            #endregion
             * */

            ViewBag.OrderId = id;

            return View(bagQuery.ToList());
        }
        #endregion

        #region Hien thi chi tiet tung BagNo
        public ActionResult BagProcessDetail(string id = null)
        {
            // lay bag
            BAG bag = db.BAGs.Find(id);
            if (bag == null)
            {
                return View();
            }

            ViewBag.KindName = db.KINDs.Where(m => m.Id == bag.ORDER_PRODUCT.Kind).FirstOrDefault().Name;

            return View(bag);
        }

        [HttpPost]
        public ActionResult BagProcessDetail(FormCollection fc, BAG bag)
        {
            return RedirectToAction("ExportReportBag", "Report", new { bagIds = new List<string> { bag.Id } });
        }

        public PartialViewResult PartialBagProcessDetail(ItemBag ib)
        {
            return PartialView(ib);
        }
        #endregion

        #region Xu ly Products In cart

        public ActionResult SaveToDb(List<ProductOrderViewModel> productions, OrderViewModel orderViewModel)
        {            
            bool result = true;

            // convert from view model to entity
            ORDER order = new ORDER();
            order.IdOrder = orderViewModel.IdOrder;
            order.IdCustomer = orderViewModel.IdCustomer;
            order.StartWeek = orderViewModel.StartWeek;
            order.FinishWeek = orderViewModel.FinishWeek;

            db.ORDERs.Add(order);

            foreach (var item in productions)
            {
                ORDER_PRODUCT op = new ORDER_PRODUCT();
                op.IdOrder = order.IdOrder;
                op.IdProduct = item.ProductId;
                int? kindId = db.KINDs.Where(m => m.Name == item.Kind).Select(m => m.Id).FirstOrDefault();
                if (kindId.HasValue)
                {
                    op.Kind = kindId.Value;
                }
                else
                {
                    return Json(new { result }, JsonRequestBehavior.AllowGet);
                }
                op.Size = item.Size;
                op.Weight = Math.Round(item.Weight, 3);
                op.Number = item.Quantity;

                db.ORDER_PRODUCT.Add(op);
            }

            // luu xuong db truoc khi chia order
            db.SaveChanges();
            // Chia order thanh cac bagNo
            DivideBagNos(order, productions);    
            this.ClearForm();

            // save data to database
            return Json(new { result}, JsonRequestBehavior.AllowGet);
        }

        public ActionResult GetProducts(string query = null)
        {
            var result = from d in db.PRODUCTs
                         where d.Id.Contains(query)
                         select d.Id;
            var s = result.ToList();
            return Json(result.ToList(), JsonRequestBehavior.AllowGet);
        }

        public ActionResult GetKinds(string query = null)
        {
            var result = from d in db.KINDs
                         where d.Name.Contains(query)
                         select new { d.Id, d.Name };
            var s = result.ToList();
            return Json(result.ToList(), JsonRequestBehavior.AllowGet);
        }

        public JsonResult ClearForm()
        {
            bool result = true;

            // reset lai order
            order.Order = new ORDER();
            order.Products.Clear();

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult AddProductToCart(int index, string productId, int kindId, string kind, double size, double weight, int quantity)
        {
            bool result;
            OrderProduct p = new OrderProduct();

            p.Index = index;
            p.ProductId = productId;
            p.KindId = kindId;
            p.Kind = kind;
            p.Size = size;
            p.Weight = Math.Round(weight, 3);
            p.Quantity = quantity;

            order.Products.Add(p);
            result = true;

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult IsOrderExisted(string id)
        {
            bool result;

            ORDER tmpOrder = db.ORDERs.Find(id);
            if (tmpOrder == null)
            {
                result = false;
            }
            else
            {
                result = true;
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult IsProductExisted(string id)
        {
            bool result;

            PRODUCT p = db.PRODUCTs.Find(id);
            if (p == null)
            {
                result = false;
            }
            else
            {
                result = true;
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult IsKindNameExisted(string kindName)
        {
            bool result;

            var query = (from d in db.KINDs
                        where d.Name == kindName
                        select d).FirstOrDefault();

            if (query == null)
            {
                result = false;
            }
            else
            {
                result = true;
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult UpdateProductInCart(int index, double size, double weight, int quantity)
        {
            bool result;
            OrderProduct p = order.Products.Find(m => m.Index == index);
            if (p == null)
                result = false;
            else
            {
                p.Kind = kinds.Where(m => m.Id == p.KindId).Select(m => m.Name).FirstOrDefault();
                p.Size = size;
                p.Weight = Math.Round(weight, 3);
                p.Quantity = quantity;

                result = true;
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult DeleteProductInCart(int index)
        {
            bool result = true;
            OrderProduct p = order.Products.Find(m => m.Index == index);
            if (p == null)
            {
                result = false;
            }
            else
            {
                order.Products.Remove(p);
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }
        #endregion

        #region Xy ly Processes In Bag No
        public JsonResult UpdateProcessInBag(int processId, string bagId, int workerId, double weightIn, double weightOut, Nullable<DateTime> dateIn, Nullable<DateTime> dateOut)
        {
            bool result = true;
            var query = from d in db.BAG_PROCESS
                        where d.IdBag == bagId && d.IdProcess == processId
                        select d;
            if (query.Count() == 0)
            {
                result = false;
            }
            else
            {
                BAG_PROCESS bp = query.First();
                bp.WorkerId = workerId;
                bp.WeightIn = Math.Round(weightIn, 3);
                bp.WeightOut = Math.Round(weightOut, 3);
                bp.DateIn = dateIn;
                bp.DateOut = dateOut;

                db.SaveChanges();
                result = true;
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }

        public JsonResult SaveOtherInfo(string id, int? finishWeek, string remark)
        {
            bool result;
            if (id == null)
            {
                result = false;
            }
            else
            {
                BAG b = db.BAGs.Find(id);
                if (b == null)
                {
                    result = false;
                }
                else
                {
                    if (finishWeek.HasValue)
                    {
                        //b.Finish = finishWeek;
                    }

                    if (remark != null && remark != b.Remark)
                    {
                        b.Remark = remark;
                    }

                    db.SaveChanges();
                    result = true;
                }
            }

            return Json(new { result }, JsonRequestBehavior.AllowGet);
        }
        #endregion
    }
}